home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
advbas26.arc
/
ADVBAS.DOC
next >
Wrap
Text File
|
1986-09-19
|
56KB
|
2,509 lines
ADVBAS.LIB v2.6, 9/19/86
Advanced Function Library for the BASIC Compiler
Copyright (C) Thomas Hanlin III, 1985, 1986
Requirements:
An IBM PC or compatible with the IBM BASIC Compiler or the Microsoft
QuickBASIC Compiler. PC-DOS/MS-DOS versions 2.0 or higher should be used.
The BASIC Compiler is a powerful and flexible tool. However, it suf-
fers from a number of serious limitations. The early versions were designed
for DOS v1, and cannot handle version 2+ functions such as subdirectories;
there is little direct access to many advanced DOS features such as selective
screen scrolling; and the speed is not all that it might be, for all its
improvement over interpreted BASIC. To reduce these problems, I've designed
a number of assembly language routines which perform desirable functions,
and put them in a library which the compiler can access. Since I have found
these functions to be useful, I thought I'd pass them on to other people.
You may use ADVBAS functions in any of your programs. If you do so, I would
appreciate you sending a contribution (recommended amount $25, which will
get you a disk containing the source code to these routines, an explanation
of how BASIC tokenizes programs, a crossreference utility, a communications
program [Eterm] with source, and lots more; registered users may receive
updates for $10). It would also be nice if you acknowledged use of these
routines in your program. ADVBAS may be copied and distributed freely as
long as it and this manual are included unchanged. The copyright is to pre-
serve my options, and to protect you from the untoward modifications of
others. It is not intended to prevent the free distribution of ADVBAS.
To use ADVBAS functions, you must copy ADVBAS.LIB to the disk on which
you keep your BASIC Compiler library files. When you compile a program which
uses an ADVBAS function, you must specify ADVBAS (preceeded by a drive letter
if it's on a different disk than the program you're compiling) when LINK asks
you which libraries to use. That is, at the LINKer prompt "Libraries [.LIB]:"
you should say "ADVBAS" (without the quotes!).
These functions have not caused me any problems, and seem to be fully
debugged; however, I will not be responsible for any damages caused by use,
misuse, or inability to use ADVBAS. But I'll try my best to fix any problems
you may turn up! Keep in mind that ADVBAS functions will work only with the
compiler, not the interpreter.
Aside from their convenience, these functions:
1) add abilities which are not otherwise available;
2) are generally faster than the corresponding Compiled BASIC code;
3) usually take up less space in the resulting EXEcutable file;
4) often leave you more free programming space.
Operation Notes
Function Requirements:
Numeric variables used in function calls must be integers unless specified
otherwise. Either declare them using DEFINT, or add a percent sign "%" to
the end of the variable name. Strings sometimes must be defined to a certain
minimum length, due to limitations on what machine language routines are
allowed to do to strings. Follow the guidelines for each routine in these
respects, or the program will not work as expected!
Compatibility:
These functions vary in what they demand of your PC. Some functions
will work only on IBM PCs or clones, some will work on compatibles, and some
will work on any MS-DOS routine. The compatibility level of each function
is now listed, using the categories CLONE (will work on hardware compatibles
only), BIOS (close compatibles), DOS (any MS-DOS machine), and ANY (hardware
independent). Be warned that the BASIC Compiler itself does not produce parti-
cularly compatible code (BASIC video routines seem to be BIOS-compatible,
etc).
QuickBASIC 2.0:
You can't use ADVBAS (or any assembly-language routines) with QB2 when
the compile-to-memory option is on. To use ADVBAS, either compile your prog-
rams using the old "separate compilation method" (QB manual, page 538), or
set the compiler to either "Compile to .OBJ module" option. You can get to
the latter from the QB environment by typing ALT-R, then choosing the
"Compile..." option, then picking the "Compile to .OBJ module" option. See
your QB reference if you can't figure out how to do this-- for an "intuitive"
environment, the new setup is awfully counterintuitive.
Please mail contributions, suggestions for additional functions, ques-
tions, comments, etc. to the following address:
Thomas Hanlin III
6812 Sydenstricker Rd
Springfield, VA 22152
Routine Reference
Disk:
DelSub, GetSub, MakeSub, SetSub: subdirectory handling
GetDrv, SetDrv: default drive control
DrvSpace: space left on a given drive
GetFdate, GetFtime, SetFTD, GetFattr, SetFattr: file info control
FindFirstF, FindNextF: read file directory
GetNameF, GetDateF, GetTimeF, GetAttrF, GetSizeF: file dir control
Keyboard:
GetKey: get one of a list of valid keys
KeyPress: see if a key has been pressed
String:
Bsq, BusqLen, Busq: text compression/decompression
Locase, Upcase: case conversion
MultiAnd, MultiOr, MultiXor: bit manipulations on chars in a string
Strip, StripRange: deletion of certain chars from a string
LRotate, RRotate, Reverse: reorder chars in a string
Xlate: run the chars of a string through a translation table
Extract: extract delimited substrings from a string using an index
Soundex: return the Soundex code of a string
Checksum, CRC: error checking (for telecom and other uses)
Array:
AddMatI, SetMatI: integer array manipulation
ReadBitF, WriteBitF: handle arrays of arbitrary bit length
Video:
DMprint, Mprint, MprintC, Qprint, XQprint: various print routines
ClrEol, BkSpace, DelChr, InsChr, MDelChr, MInsChr: screen control
Mwindow, Scroll, BkScroll: window control
ScrSave, ScrRest, GetLine: save/restore the contents of a screen
ScrSaveP, ScrSavePD, ScrRestP, ScrRestPD: variants on the above
ReColor: change any screen color to another w/o clearing screen
Miscellaneous:
Any2Dec, Dec2Any: radix conversion (decimal <--> another base)
GetDOSv: get the version number of the MS-DOS being used
SetComm: set up any comm port to any baud, without closing communications
WeekDay: returns the day of the week, Sunday through Saturday
Compatibility Chart
Works on ANY machine:
ADDMATI, ANY2DEC, BSQ, BUSQ, BUSQLEN, CHECKSUM, CRC, DEC2ANY, EXTRACT,
GETLINE, LOCASE, LROTATE, MULTIAND, MULTIOR, MULTIXOR, READBITF, REVERSE,
RROTATE, SETMATI, SOUNDEX, STRIP, STRIPRANGE, UPCASE, WRITEBITF, XLATE
Works on DOS compatibles:
DELSUB, DMPRINT, DRVSPACE, FINDFIRSTF, FINDNEXTF, GETATTRF, GETDATEF,
GETDOSV, GETDRV, GETFATTR, GETFDATE, GETFTIME, GETNAMEF, GETSIZEF, GETSUB,
GETTIMEF, MAKESUB, SETDRV, SETFATTR, SETFTD, SETSUB, WEEKDAY
Works on BIOS compatibles:
BKSCROLL, BKSPACE, CLREOL, GETKEY, KEYPRESS, MDELCHR, MINSCHR, MPRINT,
MPRINTC, MWINDOW, SCROLL, XMPRINT
Works on CLONEs (hardware compatibles):
DELCHR, INSCHR, QPRINT, RECOLOR, SCRREST, SCRRESTP, SCRRESTPD, SCRSAVE,
SCRSAVEP, SCRSAVEPD, SETCOMM, XQPRINT, XQPRINTD
Note that routines from higher sections will work on machines from lower
sections (DOS-level routines will work on BIOS- and CLONE-level machines).
It doesn't work the other way around (CLONE-level routines may not work on
a DOS-level machine).
Name: ADDMATI
Type: Miscellaneous / ANY
Description:
Adds a scalar (integer) value to the first SIZ elements of an
integer array. You can subtract by adding a negative number. If the results
of the calculation ever go outside integer range (-32768 to 32767), the
overflow flag is set on return. See SETMATI for more information.
Example:
DEFINT A-Z: OPTION BASE 1: DIM ACK(10000): SIZ=10000
.
.
ADDVAL=-6: ARLOC=VARPTR(ACK(1))
CALL ADDMATI(ARLOC,SIZ,ADDVAL,OVFLOW)
IF OVFLOW THEN PRINT"Uh oh, overflowed somewhere..."
REM we just subtracted six from each element of the array ACK.
Name: ANY2DEC
Type: Miscellaneous / ANY
Description:
Converts a number (in string form) from any base (2-35) to a decimal
integer (base 10). The number to be converted may be in either signed integer
range (-32768 to 32767) or unsigned integer range (0 to 65535). It is con-
verted to a signed integer, which is the only integer type BASIC supports.
Example:
INPUT"Number, base of number";ANUM$,NBASE
CALL ANY2DEC(ANUM$,NBASE,DNUM,ERCD)
IF ERCD THEN PRINT"Bad number!" ELSE PRINT"Decimal: ";DNUM
Name: BKSCROLL
Type: Video / BIOS
Description:
The same as SCROLL (q.v.), but scrolls lines in the opposite direction
(Back Scroll).
Example:
CALL BKSCROLL(LEFTCOL,TOPROW,RTCOL,BOTROW,NUMLINES)
Name: BKSPACE
Type: Video / BIOS
Description:
Move cursor back one space, destroying the character on the space moved
to. Will wrap from one line to the next higher if necessary. If at the top
left corner of the screen, no action is performed. Two arguments return the
new cursor coordinates, since machine language programs cannot directly change
the BASIC cursor position.
Example:
CALL BKSPACE(COL,ROW) : LOCATE ROW,COL
Name: BSQ
Type: String / ANY
Description:
Uses several techniques to compress blank spaces out of an ASCII string.
Savings range from 16% (reliable, for ordinary text) to up around 50% or more
for space-intensive info, such as lines in an assembly source file. BSQ cannot
handle more than 127 spaces in a row on a single line, or lines which contain
ASCII characters greater than 127 (which are IBM-specific graphics
characters). Do not use BSQ on lines which may contain such information!
BSQ compression is designed to produce printable (if odd-looking) text which
you may read/write to ordinary sequential files.
Example:
INPUT"String to squeeze";ST$: CALL BSQ(ST$,SLEN)
PRINT"Squeezed string: ";LEFT$(ST$,SLEN)
Name: BUSQ
Type: String / ANY
Description:
Decompresses a line squeezed by BSQ. Use BUSQLEN before this routine
to find out how long the unsqueezed line will be!
Example:
see BUSQLEN
Name: BUSQLEN
Type: String / ANY
Description:
Tells how long a line squeezed with BSQ will be once it's unsqueezed.
You must use this before unsqueezing the line with BUSQ.
Example:
CALL BUSQLEN(ST$,SLEN)
IF SLEN<0 THEN line is not squeezed, or got damaged somehow-- exit!
ELSE UNSQ$=SPACE$(SLEN): CALL BUSQ(ST$,UNSQ$)
Name: CHECKSUM
Type: Miscellaneous / ANY
Description:
Calculates a checksum for a record. Can be used with Xmodem or Ymodem.
Example:
CALL CHECKSUM(REC$,CHKSM)
Name: CLREOL
Type: Video / BIOS
Description:
Clear from cursor position to end of line. Doesn't move the cursor.
No arguments.
Example:
CALL CLREOL
Name: CRC
Type: Miscellaneous / ANY
Description:
Calculates a cyclical redundancy check value for a record. Can be used
with Xmodem CRC or Ymodem CRC.
Example:
Sending a record:
REC$=REC$+STRING$(2,0) : CALL CRC(REC$,HICRC,LOCRC) :
MID$(REC$,LEN(REC$)-1,2) = CHR$(HICRC)+CHR$(LOCRC) : send Xmodem record
Receiving a record:
CALL CRC(REC$,HICRC,LOCRC) : IF HICRC=0 AND LOCRC=0
THEN record is fine, save it
ELSE record is bad, request it to be sent again
Name: DEC2ANY
Type: Miscellaneous / ANY
Description:
Converts a number from decimal (base 10) to any other base (2-35). The
number will be converted to an unsigned integer (signed range of -32768 to
32767 is converted to unsigned range of 0 to 65535), to conform with the
built-in BASIC conversion functions HEX$ and OCT$. ANUM$ must be initialized
to the maximum size you expect the resultant number to be; this is recommended
to be 16 characters, which is the maximum length possible. The result is
right-justified in the field you provide, so if you want to keep leading
zeroes, just ignore the actual-length specification ALEN.
Example:
INPUT"Decimal number, to base";DNUM,NBASE
ANUM$ = STRING$(16,"0"): CALL DEC2ANY(DNUM,NBASE,ANUM$,ALEN)
IF ALEN<0 THEN PRINT"Bad base or ANUM$ initialized too short"
ELSE PRINT"Result: ";RIGHT$(ANUM$,ALEN)
Name: DELCHR
Type: Video / CLONE
Description:
Deletes a character from the specified location on the screen. The char-
acter at that location will disappear, and all characters to the right of
it on the same screen line will be shifted left one space. This function
should work on either color or monochrome monitors, in either 40 or 80 column
text modes. The first page only (color monitor) is supported, and graphics
modes won't work.
Example:
COL = POS(0): ROW = CSRLIN: CALL DELCHR(ROW,COL)
Name: DELSUB
Type: Disk / DOS
Description:
Deletes a subdirectory. Parameters used are the same as in SETSUB.
Note that you may not delete a subdirectory if it has any files left in it,
or if it is the main directory, or if it is the current default subdirectory.
Example:
TMP$ = SUB$+CHR$(0): CALL DELSUB(TMP$,ERRCODE)
IF ERRCODE THEN couldn't delete subdir ELSE subdir deleted
Name: DMPRINT
Type: Video / DOS
Description:
Displays a string at the current cursor position, using DOS calls for
output (so device drivers such as ANSI.SYS will work). This routine is consid-
erably faster than MPRINT (q.v.), but offers fewer amenities. Character trans-
lation is limited to what DOS provides, meaning that, for instance, Backspace
just moves the cursor back without wiping out the previous character. Other
control codes may not be translated as you might hope, either. Finally, since
DOS provides no way of finding the current print position, you have to figure
out where the cursor will be yourself if you need it (like other display rou-
tines, DMPRINT does not update the BASIC cursor position). You can gain con-
trol of such things by using the ANSI.SYS driver. See your DOS manual for
more information on that.
Example:
CALL DMPRINT(ST$)
Name: DRVSPACE
Type: Disk / DOS
Description:
Returns the amount of free space left on a given disk drive. The drive
string may be any legal disk drive, or "@" (AT sign) for the default drive,
and must be at least one character long. An illegal drive or other error
will cause free space to be returned as a negative value.
Example:
DRV$="A:"
.
.
CALL DRVSPACE(DRV$,A,B,C): FREE# = CDBL(A)*CDBL(B)*CDBL(C)
PRINT"Free space on drive ";DRV$;" is";FREE#;"bytes."
Name: EXTRACT
Type: String / ANY
Description:
Extracts a delimited substring from a string given an index. Requires
a string of any length, a delimiter of length one character, and an index
value from 1-256; returns the starting location and length of the substring.
If the delimiter is null (an error), the substring length will be returned
as -1. If the index value is greater than the number of delimited substrings,
a null substring will be returned.
Example:
ST$="John Doe/15 Maple Rd/Hometown, CA 99199/(300) 111-1111"
INDEX=2: DELIMITER$="/": CALL EXTRACT(ST$,DELIMITER$,INDEX,START,SLEN)
PRINT MID$(ST$,START,SLEN)
REM This will print the second substring (INDEX=2) of the string
REM (ST$) delimited by "/" (DELIMITER$), which in this case will
REM be "15 Maple Rd".
Name: FINDFIRSTF
Type: Disk / DOS
Description:
Given a filename (which may contain the wildcards "*" and "?", and a
drive and path spec if you like), this searches the default (or specified)
directory to find the first matching file. Further matches can be obtained
through the FINDNEXTF routine (q.v.). If there is a match, ERCD will return
zero, otherwise it will return a positive value (unless you entered a null
filename, in which case ERCD will be -1 to flag an error). You can retrieve
various information about the matched file via a number of supplementary
functions: GETNAMEF to get the filename, GETATTRF to get the attribute (there's
a page at the end of this document on file attributes), GETDATEF and GETTIMEF
to get the date and time, and GETSIZEF to get the file size. You may specify
a search attribute as well: 0 (zero) to match normal files, 2 to match hidden
files, 4 for system files, and 16 for subdirectories. Attributes other than
zero will return normal files as well as the specified type, and you can match
on more than one kind of attribute (for instance, to get all kinds of files,
you'd use an attribute of 22, or 2+4+16). You can read the volume label using
an attribute of 8, which will return only the volume label... supposedly.
In actual practice, the read-volume-label routine is not entirely reliable,
so be sure to check the attribute of the matched file to make sure that it
is in fact 8.
This function can be used to duplicate the DOS directory command, or
to allow filename wildcards in your program, among other things.
Example:
FIL$=FIL$+CHR$(0): CALL FINDFIRSTF(FIL$,ATTR,ERCD)
IF ERCD THEN PRINT"No matching files"
Name: FINDNEXTF
Type: Disk / DOS
Description:
This is used after the FINDFIRSTF function (q.v.) in order to find further
matching files.
Example:
CALL FINDNEXTF(ERCD)
IF ERCD THEN PRINT"No more matching files"
Name: GETATTRF
Type: Disk / DOS
Description:
Returns the actual attribute of a file matched using FINDFIRSTF or
FINDNEXTF. See the end of this document for information on file attributes.
Example:
REM use this AFTER calling FINDFIRSTF / FINDNEXTF to initialize
REM the appropriate file information!
CALL GETATTRF(ATTR)
Name: GETDATEF
Type: Disk / DOS
Description:
Returns the date associated with the file matched using FINDFIRSTF or
FINDNEXTF.
Example:
CALL GETDATEF(MONTH,DAY,YEAR)
Name: GETDOSV
Type: Miscellaneous / DOS
Description:
Gets MS-DOS version. The major version is returned in the first para-
meter, the minor version in the second (e.g., MS-DOS v. 2.11 would return
MAJ = 2, MIN = 11).
Example:
CALL GETDOSV(MAJ,MIN)
Name: GETDRV
Type: Disk / DOS
Description:
Returns the letter of the default drive. The drive string must be at
least one character long.
Example:
DRV$="x:" : CALL GETDRV(DRV$)
Name: GETFATTR
Type: Disk / DOS
Description:
Gets file attribute. See section on file attributes at the end of this
manual.
Example:
FIL$ = FIL$ + CHR$(0): CALL GETFATTR(FIL$,ATR)
Name: GETFDATE
Type: Disk / DOS
Description:
GETFDATE returns the file creation date, that is, the date you see on
a file when you get a DIRectory. The file name must be terminated with an
ASCII NUL character. If there is an error, such as there being no such file,
the month will be -1.
Example:
FIL$ = "TESTFILE.TXT" + CHR$(0)
CALL GETFDATE(FIL$,MONTH,DAY,YEAR)
Name: GETFTIME
Type: Disk / DOS
Description:
This function complements GETFDATE, and returns the file creation time.
The hour is in 24-hour (military) format, and will be returned as -1 if there
is no such file or a bad file name. The seconds are rounded to the next lower
even number, due to the DOS storage format. The file name must be terminated
with an ASCII zero, or NUL character.
Example:
FIL$ = "ANYFILE.EXT" + CHR$(0)
CALL GETFTIME(FIL$,HOUR,MINUTE,SECOND)
Name: GETKEY
Type: Keyboard / BIOS
Description:
Waits until one of a list of keys is pressed, and returns it. The key
list (any length) should be uppercase, and if the length is null, the first
key pressed will be returned. The key returned will be capitalized. The
variable to return the key in must be at least one character long. This func-
tion is designed for returning one of a menu of choices, for example.
Example:
GOODKEYS$="KEY LIST"
.
.
KY$="x": CALL GETKEY(GOODKEYS$,KY$)
Name: GETLINE
Type: Video / ANY
Description:
Returns a selected line from a screen saved via SCRSAVE, with the trailing
spaces removed. The line string must be at least 80 characters long.
Example:
DEFINT A-Z: OPTION BASE 1: DIM SCR(2000)
WHERE=VARPTR(SCR(1)): CALL SCRSAVE(WHERE): CLS
LINENR=10: LIN$=SPACE$(80): WHERE=VARPTR(SCR(1))
CALL GETLINE(WHERE,LINENR,LIN$,LLEN)
PRINT"Line 10 was:": PRINT LEFT$(LIN$,LLEN)
Name: GETNAMEF
Type: Disk / DOS
Description:
Returns the filename of the file matched using FINDFIRSTF or FINDNEXTF.
The FIL$ string must be initialized to at least 12 characters in length.
The actual length of FIL$ will be returned in FLEN, which will be -1 if you
didn't initialize FIL$ long enough. Note that the filename will not contain
a drive or path spec.
Example:
FIL$ = SPACE$(12): CALL GETNAMEF(FIL$,FLEN): FIL$ = LEFT$(FIL$,FLEN)
Name: GETSIZEF
Type: Disk / DOS
Description:
Returns the size of the file matched via FINDFIRSTF or FINDNEXTF. Since
the file size may be outside integer bounds, there is some additional code
you will have to add which uses double-precision values (see the example).
You can modify the example to use single-precision instead, but really large
file sizes will then lapse into exponential notation.
Example:
CALL GETSIZEF(SIZELOW,SIZEHIGH): SIZELOW# = CDBL(SIZELOW)
IF SIZELOW < 0 THEN SIZELOW# = SIZELOW# + 65536#
FILESIZE# = SIZELOW# + CDBL(SIZEHIGH) * 65536#
Name: GETSUB
Type: Disk / DOS
Description:
Gets the default subdirectory. The subdirectory string must be 64 charac-
ters long, and it is recommended that you set it to ASCII zeroes (the NUL
character). The length of the subdirectory string is returned as an integer
value. Note that the string will NOT be started by a backslash "\" character--
you should add one if appropriate.
Example:
SUB$ = STRING$(64,0) : CALL GETSUB(SUB$,SLEN) :
SUB$ = "\" + LEFT$(SUB$,SLEN)
Name: GETTIMEF
Type: Disk / DOS
Description:
Returns the time associated with the file matched by FINDFIRSTF or
FINDNEXTF. The hour is returned in military (24-hour) format.
Example:
CALL GETTIMEF(HOUR,MINUTE,SECOND)
Name: INSCHR
Type: Video / CLONE
Description:
Inserts a space at the specified screen location. The character previous-
ly at that position and all characters to the right of it on the same screen
line will be shifted right one space. Subject to the same limitations as
DELCHR (q.v.).
Example:
COL = POS(0): ROW = CSRLIN: CALL INSCHR(ROW,COL): PRINT"*";
Name: KEYPRESS
Type: Keyboard / BIOS
Description:
Tells you whether a key is waiting in the keyboard buffer (for use with
INKEY$ routines, etc). KYHIT is set to -1 if a key is waiting, 0 otherwise.
Example:
100 CALL KEYPRESS(KYHIT):IF KYHIT THEN KY$=INKEY$:GOTO 300 ELSE 100
Name: LOCASE
Type: String / ANY
Description:
Converts a string to all lowercase. Leaves non-alphabetic characters
untouched. String may be any length.
Example:
MSG$="THis IS a test OF tHe lowercase CONVERTER!"
.
.
CALL LOCASE(MSG$)
Name: LROTATE
Type: String / ANY
Description:
Rotates the characters in a string left. That is, the leftmost character
is removed, and tacked onto the end of the string. This is useful for rotating
queues and for character-graphics animation. If the string is of length one
or less, it is returned unchanged.
Example:
ST$ = "12345": CALL LROTATE(ST$)
REM ST$ will end up being "23451"
Name: MAKESUB
Type: Disk / DOS
Description:
Makes a subdirectory. Parameters used are the same as in SETSUB.
Example:
TMP$ = SUB$+CHR$(0): CALL MAKESUB(TMP$,ERRCODE)
IF ERRCODE THEN couldn't make subdir ELSE subdir created
Name: MDELCHR
Type: Video / BIOS
Description:
Deletes the character at the current cursor position. It obeys the window
defined by MWINDOW. It's more compatible than DELCHR, but much slower.
Note that this routine can be used to scroll a window left by doing
an MDELCHR at the first location of each line to be scrolled. To scroll right,
do the same using MINSCHR instead.
Example:
CALL MDELCHR
Name: MINSCHR
Type: Video / BIOS
Description:
Inserts a space at the current cursor position, obeying the window defined
by MWINDOW. See notes at MDELCHR.
Example:
CALL MINSCHR
Name: MPRINTC
Type: Video / BIOS
Description:
Using this function, you can at last access device drivers such as
ANSI.SYS. This is a video output function which goes through MS-DOS function
calls. It prints a single character to the display. Advantages: allows use
of ANSI.SYS and similar video drivers, and windowing via MWINDOW.
Disadvantages: is slower and takes more memory that the usual PRINT statement.
Example:
CALL MPRINTC(CH$,COL,ROW): LOCATE ROW,COL
Name: MPRINT
Type: Video / BIOS
Description:
Same as MPRINTC (q.v.), only it allows you to send an entire string out
to the display, rather than just a single character.
Example:
CALL MPRINT(ST$,COL,ROW): LOCATE ROW,COL
Name: MULTIAND
Type: String / ANY
Description:
This is a flexible function with many possible uses. Every character
in a given string is ANDed with a value you supply. One thing this could
be used for is translating Wordstar files to ASCII files, by using a bit mask
(the value that will be ANDed with the character) of &H7F, which strips off
the high bit of each character. The string may be any length; the bit mask
is an integer, with only the low byte in use (value of 0-255).
Example:
ST$ = "" : FOR X=65 TO 70: ST$ = CHR$(X)+CHR$(X+128): NEXT : PRINT ST$
BITMASK = &H7F : CALL MULTIAND(ST$,BITMASK) : PRINT ST$
Name: MULTIOR
Type: String / ANY
Description:
Does the exact opposite of MULTIAND-- instead of stripping off bits,
it turns on bits. It ORs instead of ANDs. One possible use for this would
be to encode a text string by ORing with 128, and later decoding by ANDing
with 128. This would allow you to save the string to disk using text files,
even if the string included control codes. It won't work right if the string
has graphics characters (using ExtASCII codes, which are codes from 128-255)
in it, though. The parameters are the same as for MULTIAND.
Example:
ST$ = "ABCDE": PRINT ST$: SETBITS = &H80
CALL MULTIOR(ST$,SETBITS): PRINT ST$
Name: MULTIXOR
Type: String / ANY
Description:
An exclusive-or operation for strings. Bits in the string will be set
only if they are set in the string byte or mask byte, but not in both of them.
Note that this can be used as a "MULTINOT" function by using a mask of &HFF
or 255. In this case, all bits are set in the mask, so the result of the
XOR will be the same as a NOT operation on the string. Note that XORing a
string with the same value twice will return the original string-- it can
thus be used to encode and decode strings.
Example:
CALL MULTIXOR(ST$,MASK)
Name: MWINDOW
Type: Video / BIOS
Description:
Sets up a window for the MPRINT and MPRINTC routines. Windows are defined
by their upper left corner and lower right corner. The default window is
thus (0,0,80,24), which leaves out the bottom line (BASIC's status line).
To use the full screen, call this routine with values (0,0,80,25). Note that
the cursor should be positioned inside the window before using MPRINT/MPRINTC.
Note also that windows should be defined to contain at least two rows.
Example:
LFTCOL = 20: TOPROW = 5: RTCOL = 60: BOTROW = 15
CALL MWINDOW(LFTCOL,TOPROW,RTCOL,BOTROW): LOCATE TOPROW,LFTCOL
REM sets up a window in the middle of the screen
REM of 40 cols by 10 rows.
Name: QPRINT
Type: Video / CLONE
Description:
This function bypasses the usual video routines, and prints a string
directly on the screen, at a -much- higher speed than the normal PRINT state-
ment does. It also contains a built-in LOCATE statement, and doesn't affect
the cursor position. The string may be any length. Control characters will
show up as graphics characters instead of having their original functions,
and the color/attributes used will be the ones already on the screen. This
works for 40 or 80 column displays, monochrome or color. Display page zero
will be used (if applicable).
Note: this function appeared in BYTE magazine in a different form, and
has been modified several times since. It is not solely my creation. See
the source code for further information.
Example:
ST$ = "This is a test of fast screen printing"
ROW = 10: COL = 20
CALL QPRINT(ST$,ROW,COL)
Name: READBITF
Type: Miscellaneous / ANY
Description:
Reads a word from an array of arbitrary bit length, given an index.
The words in the array may be made of one to eight bits. Indices begin at
zero and are limited by integer range. That is up to &HFFFF, subject to memory
constraints-- the index is taken to be an unsigned integer value. This func-
tion allows very memory-efficient storage of arrays of numbers, provided that
the numbers are within a restricted range. The simulated array is held within
a normal integer array, which must be dimensioned large enough to hold all
of the arbitrary-length words (will depend on bits per word and number of
words desired).
Example:
OPTION BASE 0: DEFINT A-Z: DIM INTARRAY(50): BITFSIZE=8
.
.
ARRAYLOC=VARPTR(INTARRAY(0))
CALL READBITF(ARRAYLOC,NDX,BITFSIZE,VALUE)
REM Returns a value from the array location indexed by NDX,
REM where the array is composed of bytes (8-bit words).
REM See the disk file BITFTEST.BAS in the \SOURCE subdirectory
REM for a working example program (compiled BASIC only!!!)
Name: RECOLOR
Type: Video / CLONE
Description:
Takes everything on the screen that's of a given color and changes its
color to whatever you like. This can be used for special effects, or just
to change the screen color without having to clear the screen. This will
work on either mono or color monitors, in text modes only. The color attribute
must be defined from the foreground and background colors using the formula
shown below.
Example:
OLDCOLR = (BGNDCOLR AND 7)*16 + FGNDCOLR
NEWCOLR = (NEWBGNDCOLR AND 7)*16 + NEWFGNDCOLR
CALL RECOLOR(OLDCOLR,NEWCOLR)
Name: REVERSE
Type: String / ANY
Description:
Reverses the order of characters in a string. This can be combined with
the XLATE function and a judiciously-designed translation table to provide
mirror images of strings for character-graphics-based displays.
Example:
MSG$="This is a test": CALL REVERSE(MSG$): PRINT MSG$
Name: RROTATE
Type: String / ANY
Description:
Rotates the characters in a string right. This is the same as LROTATE,
only in reverse. See LROTATE for further details.
Example:
ST$ = "12345": CALL RROTATE(ST$)
REM ST$ will end up being "51234"
Name: SCROLL
Type: Video / BIOS
Description:
Scrolls any selected portion of the screen as many times as you like
(1-255, or use 0 to clear that part of the screen entirely). Five arguments
give coordinates (LEFTCOL,TOPROW) of the upper left corner of the area to
be scrolled, coordinates (RTCOL,BOTROW) of the lower right corner of the area
to be scrolled, and the number of times to scroll the area. This routine
may be used to create windows. Note that RTCOL must be at least one greater
than LEFTCOL (no single-line scrolling, obviously). Parameters are not
checked, so be careful not to use illegal screen coordinates.
Example:
CALL SCROLL(LEFTCOL,TOPROW,RTCOL,BOTROW,NUMLINES)
Name: SCRREST
Type: Video / CLONE
Description:
Restores the screen display from an image put into an array by SCRSAVE.
Same requirements and limitations of SCRSAVE.
Example:
WHERE = VARPTR(SCR(1)): CALL SCRREST(WHERE): LOCATE OLDROW,OLDCOL
Name: SCRSAVE
Type: Video / CLONE
Description:
Stores the current screen display (page 0 only) in an array. Text modes
only. Requires an array of 4000 bytes, and an integer which points to the
location of the array. The cursor position is not saved.
Example:
DEFINT A-Z: OPTION BASE 1: DIM SCR(2000)
.
.
WHERE = VARPTR(SCR(1)): CALL SCRSAVE(WHERE)
OLDCOL = POS(0) : OLDROW = CSRLIN
REM Dim of 2000 w/ option base 1 gives us 2000 integers, each of
REM which occupy two bytes, giving 4000 bytes of storage space.
REM Note: you can store more than one screen in an array by
REM dimensioning it large enough. Use WHERE=VARPTR(SCR(2001))
REM to locate the second screen, and so forth.
Name: SCRRESTP, SCRRESTPD, SCRSAVEP, SCRSAVEPD
Type: Video / CLONE
Description:
These functions are variations of SCRREST and SCRSAVE. All of them allow
specification of a page number, for color monitors. They will save or restore
text to a given page. When used with monochrome monitors, the page specifica-
tion should always be zero. SCRRESTPD and SCRSAVEPD write directly to the
screen at high speed. This will cause "snow" if you have an old or poorly
designed color display adapter and are writing to the active screen page.
Under those conditions, you should use SCRRESTP/SCRSAVEP or SCRREST/SCRSAVE.
Example:
WHERE = VARPTR(SCR(1)) : SCRNPAGE = 0
CALL SCRRESTP(WHERE,SCRNPAGE) : LOCATE OLDROW,OLDCOL
Name: SETCOMM
Type: Miscellaneous / CLONE
Description:
Sets communications parameters on an opened communications device. This
allows you to set the baud rate higher than BASIC normally allows, and to
change the comm parameters without having to close the comm device.
Note that BASIC currently limits access to comm ports one and two. You
can set parms on ports 1-4 using SETCOMM, however. Hopefully a future release
of ADVBAS will allow you to use the other two ports if you have them.
Why is it bad to have to close the comm device? Because that will make
the DTR signal drop, which will cause many modems to drop the carrier and
lose your connection. In fact, for Hayes-type modems, that's a much more
reliable way to end communications than using the ATH modem command.
If you try to set a comm port which does not exist, the port number will
be set to zero after the call. If you give illegal parameters elsewhere,
the port will be set to a default of 300 baud, Even parity, Seven-bit words,
and One stop bit (any of the parms which were legal will be used).
Example:
OPEN"R",1,"COM1:300,E,7,1,RS,CS,DS"
COMMPORT = 1 : BPS = 6 : PARITY = 0 : WORDLENGTH = 8 : STOPBITS = 1
CALL SETCOMM(COMMPORT,BPS,PARITY,WORDLENGTH,STOPBITS)
REM sets the port to 19200 baud, No parity, 8 bit words, 1 stop bit.
Settings:
COMMPORT may be 1 - 2, and will be returned as 0 if the specified port
doesn't exist. Four ports are allowed, but you can only access 1 and 2.
BPS ("baud rate") is specified by a number from 0 - 7. Use 0 for 300
bps, 1 for 600, 2 for 1200, 3 for 2400, 4 for 4800, 5 for 9600, 6 for 19200,
and 7 for 38400 bps. Whether you can actually get higher speeds will depend
on the quality of your communications port.
PARITY is a number 0-2. Use 0 for None, 1 for Odd, and 2 for Even.
WORDLENGTH is 7 or 8, and STOPBITS is 1 or 2, just as you'd expect.
Name: SETDRV
Type: Disk / DOS
Description:
Sets the default drive. The drive string must be at least one character
long, and start with a letter specifying a disk drive.
Example:
DRV$="B:"
.
.
CALL SETDRV(DRV$)
Name: SETFATTR
Type: Disk / DOS
Description:
Sets file attribute. See section on file attributes at the end of this
manual.
Example:
FIL$ = FIL$ + CHR$(0): CALL SETFATTR(FIL$,ATTR)
Name: SETFTD
Type: Disk / DOS
Description:
Sets file time/date stamp. The filename must be terminated with a NUL
character. The year may be either a four digit or two digit number (e.g.,
may be either 1986 or just 86). DOS will round the seconds value off to the
next lower even number. If there is a problem with the filename, the month
will be returned as -1.
Example:
FIL$=FIL$+CHR$(0)
CALL SETFTD(FIL$,MONTH,DAY,YEAR,HOUR,MINUTE,SECOND)
Name: SETMATI
Type: Miscellaneous / ANY
Description:
Sets the first SIZ elements of an integer array to a given (scalar) value,
INITVAL. It will work on multi-dimensional arrays, in which case the leftmost
dimension increments first. See examples for clarification.
Example:
OPTION BASE 0: DEFINT A-Z: DIM BANANA(9)
SIZ=10: INITVAL=-3: ARLOC=VARPTR(BANANA(0))
CALL SETMATI(ARLOC,SIZ,INITVAL)
REM we have just initialized all 10 elements of the array to
REM the value -3.
Example:
OPTION BASE 1: DEFINT A-Z: DIM FOO(3,5)
SIZ=5: INITVAL=20000: ARLOC=VARPTR(FOO(1,1))
CALL SETMATI(ARLOC,SIZ,INITVAL)
REM we have just set the first five elements of the array to
REM 20000. The first five elements are FOO(1,1), FOO(2,1),
REM FOO(3,1), FOO(1,2), FOO(2,2). If you wanted to initialize
REM the whole array to 20000, you'd set SIZ=3*5 for OPTION BASE 1,
REM or SIZ=(3+1)*(5+1) for OPTION BASE 0, in this case...
REM By changing the first element (in the ARLOC assignment), you
REM can set any part of the array, not just the first elements.
REM See SCRSAVE/SCRREST if you need to clear up that last point.
Name: SETSUB
Type: Disk / DOS
Description:
Sets the default subdirectory. The subdirectory string must be at least
one character in length, since it must be terminated by a NUL character.
A negative one will be returned if there was a problem setting to the given
subdirectory (either it's not available on the default drive, or a bad name,
most likely); else zero will be returned if all went well.
Example:
TMP$ = SUB$+CHR$(0): CALL SETSUB(TMP$,ERCD) :
IF ERCD THEN bad subdir ELSE new default subdir selected
Name: SOUNDEX
Type: String / ANY
Description:
This routine returns the Soundex code for a string you give it. I'm
not sure who invented Soundex, but it's pretty handy. The Soundex routine
takes a word and returns a string which represents what the word sounds like
in an abstract format. Similar-sounding words can thus be identified easily
by your program after Soundex processing. This can be useful in applications
where a person is not sure of the exact spelling of a word/name/city, etc.
To use, put the word in WORD$, initialize the return string SCODE$ to the
same length as WORD$, and execute the routine. SLEN% will return the actual
length of SCODE$, which may vary from zero to the length of WORD$. If SCODE$
is not as long as WORD$ when the routine is called, SLEN% will be returned
as -1 to flag an error. The Soundex code is returned as a series of digits
in SCODE$, although you can represent this any way you choose in your program.
Example:
WORD$ = "AnyWord": SCODE$=WORD$: CALL SOUNDEX(WORD$,SCODE$,SLEN)
PRINT"The Soundex code for ";WORD$;" is ";LEFT$(SCODE$,SLEN);"."
REM Try this routine a few times to get a feel for it.
Name: STRIP
Type: String / ANY
Description:
Strips all occurrences of a given target character from a given source
string. The source string may be any length; the target string must be at
least one character. The new length of the source string will be returned
as an integer, since external routines may not change the length of BASIC
strings directly.
Example:
MSG$="12 - 2 = 10"
.
.
CH$=" ": CALL STRIP(MSG$,CH$,MLEN): MSG$ = LEFT$(MSG$,MLEN)
Name: STRIPRANGE
Type: String / ANY
Description:
Strips all characters within a given range out of a source string. The
source string may be any length. The new length of the source string will
be returned as an integer.
Example:
MSG$="ALL uppercase letters will be G-O-N-E gone"
LO = ASC("A"): HI = ASC("Z")
CALL STRIPRANGE(MSG$,LO,HI,MLEN): PRINT LEFT$(MSG$,MLEN)
Name: UPCASE
Type: String / ANY
Description:
Converts a string to all uppercase. Leaves non-alphabetic characters
untouched. String may be any length.
Example:
MSG$="Four score and seven years ago"
.
.
CALL UPCASE(MSG$)
Name: WEEKDAY
Type: Miscellaneous / DOS
Description:
Returns an integer from 1 - 7 indicating the day of the week, Sunday
through Saturday. The example routine turns this integer into the week day.
Example:
CALL WEEKDAY(DAY%): DLEN% = VAL(MID$("3346535",DAY,1))
DLOC% = ASC(MID$("ADGKQVY",DAY%)): REM This string MUST be uppercase!
PRINT"Today is ";MID$("SunMonTuesWednesThursFriSatur",DLOC%,DLEN%);"day."
Name: WRITEBITF
Type: Miscellaneous / ANY
Description:
Allows a value to be written into a given location of a simulated array
of words of arbitrary bit length (1-8 bits per word). This goes with the
READBITF function above. The "BITF" is for Bit Field, because the functions
work by creating fields of arbitrary bit length within what is actually an
integer array.
Example:
CALL WRITEBITF(ARRAYLOC,INDEX,BITFSIZE,VALUE)
REM See the READBITF function, and check out the BITFTEST.BAS if you
REM have the ADVBAS contributor disk, to better idea of what these
REM functions do. This function is not for novice programmers!
Name: XLATE
Type: String / ANY
Description:
This function translates a string, character by character, using a table
you supply. The character's ASCII value is used as the index to the table,
and the value at that location replaces the character's current value. The
character may be one byte in length, in which case it will be translated,
or zero bytes, in which case nothing will happen. The translation string
must be 256 bytes long (remember, strings may be longer than 255 bytes in
Compiled BASIC, so this is ok).
Example:
XLT$ = "": FOR X=0 TO 255: XLT$=XLT$+CHR$(X): NEXT
MID$(XLT$,1,5) = "ABCDE": CH$ = CHR$(0)
CALL XLATE$(CH$,XLT$): PRINT CH$
REM CH$ ends up "A", since the start of the table + zero bytes
REM contains "A". We add zero bytes, because CH$ was
REM originally equal to CHR$(0).
Name: XMPRINT
Type: Video / BIOS
Description:
This routine combines the XLATE and MPRINTC functions. It takes a char-
acter, runs it through a translation table, and prints it to the screen unless
the translated value is NUL (ASCII zero). If it's NUL, no printing takes
place. MS-DOS calls are used for printing, so ANSI.SYS will work. See the
XLATE and MPRINTC routines for further information.
Example:
CALL XMPRINT(CH$,XLATE$,COL,ROW): LOCATE ROW,COL
Name: XQPRINT
Type: Video / CLONE
Description:
This function is an extended version of QPRINT. It is more flexible,
and only a trifle slower. XQPRINT has two advantages over QPRINT: it allows
you to choose a color/attribute to use, and lets you choose a display page
(color/graphics adapters only!). The attribute ATTR must be set up using
a special formula, and the display page is limited to a range of 0-3. This
means that in 40-column mode, the display page used will actually be twice
the argument you give the function, giving you access to 40-column display
pages 0,2,4, and 6. Or so the theory goes. The page argument is ignored
for monochrome adapters.
Example:
ST$ = "This is a test of fast screen printing"
ROW = 10: COL = 20: PAGE = 0
ATTR = (BACKGROUNDCOLOR AND 7) * 16 + FOREGROUNDCOLOR
CALL XQPRINT(ST$,ROW,COL,ATTR,PAGE)
Name: XQPRINTD
Type: Video / CLONE
Description:
This function is identical to XQPRINT, with the one exception that it
writes directly to the screen. That makes it even faster than XQPRINT, but
means that it will cause snow on some color monitors when printing to the
active display page.
File Attributes
Every file has an "attribute byte" which tells something about the file.
This can be modified to some extent. For instance, any file can be made
"hidden", in which case it will be invisible; this includes subdirectories,
which can still be used even if you can't see that they're there. Some kinds
of changes are not possible, however: you can't change a subdirectory into
a normal file, for example.
Attribute Code Description
Normal 00h A normal file.
Read-only 01h File can be renamed, but not killed or modified.
Hidden 02h File disappears from directory, can't be opened.
System 04h Like HIDDEN. Used for system (DOS, BIOS) files.
Volume-ID 08h A disk's volume id. Can only be one, in root dir.
Directory 10h Subdirectory. Can't be changed to another attribute.
Archive 20h Usually set. Sometimes used for hard disk backup.
Combinations of the codes are possible, as I've mentioned. For instance,
a hidden subdirectory would have a code of 12h. A normal file, because of
the archive bit, might show up as either 00h or 20h... and so on. Note this
is all in hexadecimal, hence the "h" postfix. Convert to decimal form as
necessary when calling routines which use the file attribute. BASIC has
functions to handle this for you if you don't understand hex-- see the HEX$
function and &H prefix in your BASIC manual.
BASCOM Bugs
(info unrelated to ADVBAS!)
Following are a few notes on BASIC Compiler bugs that I've run into.
These are not caused by the ADVBAS routines, and have no relation to them.
I just thought it might be helpful if I mentioned them, since anyone reading
this evidently has, or is considering buying, a BASIC Compiler.
IBM BASIC Compiler v1.00 (may well not apply to the current version 2):
Illegal file names return a "Bad file number" error, rather than the
expected "Bad file name".
The control codes to move the cursor left and right work fine, but not
the ones to move it up and down, which do nothing.
Register BP is not saved by the compiler when it does a CALL. This must
be done by the called routine, since this register is used by the compiler
for vital information.
The /E compiler option seems to introduce errors into some programs which
crash them by freezing the computer or giving a "String Space Corrupt" error.
If this happens, I've found you can fix it by adding the /D option, or using
/X instead of /E. The latter method cuts down heavily on available program
space, so it may not be as good as the former. Both add a fair bit to the
EXE program size. It's a hard life... This problem may also cause programs
compiled without the /O option to lock up, which can't be fixed by using /X
or /D. Use the /O option if this happens.
BASCOM Bugs
Microsoft QuickBASIC Compiler v1.00:
If there is not enough memory when you try to execute the SHELL command,
your program will crash. There is no way to avoid this using error trapping,
because the memory reallocation will have fried the stack. So even if you
trap the OUT OF MEMORY error, you'll still crash with a RETURN WITHOUT GOSUB
if you try to return from a subroutine, or a STRING SPACE CORRUPT error when
the compiler gets around to doing a string garbage collection. Bad news.
It would be nice if it tried to check to see if there was enough memory first.
The error STRING FORMULA TOO COMPLEX appears erratically in some programs,
even with the simplest possible string formulae (like V$="TEST"). This only
seems to happen in programs which do a lot of string manipulation, which
suggests that the compiler has a flaky and is doing something wrong with gar-
bage collection, or something like that. There seems to be no way to get
around this bug either-- also bad news. If you have this problem, I recommend
that you complain vociferously to Microsoft!
Microsoft QuickBASIC Compiler v1.02:
I haven't had a chance to test it out much yet, but they claim that this
release solves the SHELL crash problem. Also, more control characters are
now printed out just like BASICA. Many miscellaneous problems have been
fixed... But not the infamous STRING FORMULA TOO COMPLEX error. Sigh.
BASCOM Bugs
Microsoft QuickBASIC Compiler v2.00:
Well, this release fixes yet more compiler bugs. The STRING FORMULA
TOO COMPLEX error lives on, however. I'm going to have to track that down
and send in an example program to Microsoft, I guess, as soon as I can find
the time. A few new functions have been added, but nothing particularly use-
ful. The new programming environment (a la Turbo Pascal) is poorly designed
for an environment which is evidently supposed to mimic the "intuitive" feel
of the MacIntosh. The editor really isn't adequate, and suffers from a number
of irritating bugs. The compiler is now a massive 180K, and takes forever
to load. The "user library" feature is fairly worthless-- you can only build
libraries of BASIC subprograms with it, not assembly code; you are required
to list all the names of all the subprograms in a library whenever you modify
the library; and the user library is in its own unique format, so if you had
hoped to be able to link it with other languages, forget it. The one thing
that is good about the new version of the compiler is the manual, which is
really excellent-- enormous, clear and detailed.
Screen paging is doesn't work. Assembly routines (like ADVBAS) can't
be used in the normal mode (they generate "UNRESOLVED SUBPROGRAM" errors).
See the notes at the beginning of this document for how to get around that
problem. The editor has a defective search-and-replace function, adds blank
lines at the end of the program under certain conditions, and allows you to
put some control characters directly into the program (which gives the compiler
odd problems). When entering the filename, you have to use Shift-Backspace
instead of the Delete key to delete characters. The use of TAB, SPACE, RETURN,
and the arrow keys when making a choice on the menus is arbitrary, weird,
and counterintuitive in the extreme. If you use the old method of compiling,
bypassing the new environment, you no longer get any error messages, just
an error count. You can't get a source listing any more, either.
Wish list for QuickBASIC:
Recursive functions.
No bugs!
Production of code which can be linked with other languages.
A smaller compiler (take out the new environment and editor, please,
and put the error messages back!).
An error trapping function that returns the label of the routine where
the error took place (like ERL, only for labels).
Communications functions which don't produce errors whenever you get
the slightest bit of line noise.
BASIC Bugs
This is a peculiar one... it seems that BASIC can create files having
names which contain blank spaces. This is a problem, because DOS considers
the space to be a delimiter, and thus cannot handle these files. Such files
will not be listed correctly in the directory, and will be impossible to manipu-
late from DOS (can't read, delete, or otherwise handle the file). So, be
careful to screen out spaces when creating files from BASIC! This caveat
also applies to subdirectories, including those created with the MAKESUB
routine of ADVBAS.
Call for help:
If you find any other bugs in any IBM/Microsoft BASIC compiler, or in
ADVBAS for that matter, please let me know. If I can't fix it, at least I
can warn people!